<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Regular expressions</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="PHP, learn PHP, regular expressions, programming, language">
<meta name="description" content="In this part of the PHP tutorial, we cover regular expressions in PHP.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">

<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Regular expressions</h1>

<p>
In this part of the PHP tutorial, we will talk about regular expressions in PHP.
</p>

<p>
Regular expressions are used for text searching and more advanced text manipulation.  Regular
expressions are built-in tools like grep, sed, text editors like vi, emacs, programming 
languages like Tcl, Perl, Python. PHP has a built-in support for regular expressions too.
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* top_horizontal */
google_ad_slot = "3327173442";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<p>
In PHP, there are two modules for regular expressions. The POSIX Regex and the
PCRE. The POSIX Regex is depreciated. In this chapter, we will use the 
PCRE examples. PCRE stands for Perl compatible regular expressions.
</p>

<p>
Two things are needed, when we work with regular expressions. Regex functions and the pattern.
</p>

<p>
A <b>pattern</b> is a regular expression, that defines the text, we are searching for
or manipulating. It consists of text literals and metacharacters. The pattern is
placed inside two delimiters. These are usually //, ##, or @@ characters. They inform
the regex function where the pattern starts and ends. 
</p>

<p>
Here is a partial list of metacharacters used in PCRE.
</p>

<table>
<tr><td>.</td><td>Matches any single character.</td></tr>
<tr><td>*</td><td>Matches the preceding element zero or more times.</td></tr>
<tr><td>[  ]</td><td>Bracket expression. Matches a character within the brackets.</td></tr>
<tr><td>[^  ]</td><td>Matches a single character, that is not contained within the brackets.</td></tr>
<tr><td>^</td><td>Matches the starting position within the string.</td></tr>
<tr><td>$</td><td>Matches the ending position within the string.</td></tr>
<tr><td>|</td><td>Alternation operator.</td></tr>
</table>

<h2>PRCE functions</h2>

<p>
We define some PCRE regex functions. They all have a preg prefix.
</p>

<ul>
<li><code>preg_split()</code> - splits a string by regex pattern</li>
<li><code>preg_match()</code> - performs a regex match</li>
<li><code>preg_replace()</code> - search and replace string by regex pattern</li>
<li><code>preg_grep()</code> - returns array entries that match the regex pattern </li>
</ul>

<p>
Next we will have an example for each function.
</p>

<pre class="code">
php &gt; print_r(preg_split("@\s@", "Jane\tKate\nLucy Marion"));
Array
(
    [0] => Jane
    [1] => Kate
    [2] => Lucy
    [3] => Marion
)
</pre>

<p>
We have four names divided by spaces. The \s is a character class, which stands for spaces.
The <code>preg_split()</code> function returns the split strings. 
</p>

<pre>
php > echo preg_match("#[a-z]#", "s");
1
</pre>

<p>
The <code>preg_match()</code> function looks if the 's' character
is in the character class [a-z]. The class stands for all characters from a to z.
It returns 1 for success. 
</p>

<pre class="code">
php &gt; echo preg_replace("/Jane/","Beky","I saw Jane. Jane was beautiful.");
I saw Beky. Beky was beautiful.
</pre>

<p>
The <code>preg_replace()</code> function replaces all occurrences of 
the word 'Jane' for the word 'Beky'.
</p>

<pre class="code">
php > print_r(preg_grep("#Jane#", array("Jane", "jane", "Joan", "JANE")));
Array
(
    [0] => Jane
)
</pre>

<p>
The <code>preg_grep()</code> function returns an array of words, that
match the given pattern. In the script example, only one word is returned in the array.
This is because by default, the search is case sensitive.
</p>

<pre class="code">
php > print_r(preg_grep("#Jane#i", array("Jane", "jane", "Joan", "JANE")));
Array
(
    [0] => Jane
    [1] => jane
    [3] => JANE
)
</pre>

<p>
In this example, we perform a case insensitive grep. We put the i modifier after
the right delimiter. The returned array has three words.
</p>

<h2>The dot metacharacter</h2>

<p>
The . (dot) metacharacter stands for any single character in the text. 
</p>

<pre class="code">
&lt;?php

$words = array("Seven", "even", "Maven", "Amen", "Leven");

$pattern = "/.even/";

foreach ($words as $word) {
    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match the pattern\n";
    }
}

?&gt;
</pre>

<p>
In the <b>$words</b> array, we have five words. 
</p>


<pre class="explanation">
$pattern = "/.even/";
</pre>

<p>
Here we define the search pattern. The pattern is a string. The regular expression 
is placed within delimiters. The delimiters are not optional. 
They must be present. In our case, we use forward slashes / / as delimiters. Note, we
can use different delimiters, if we want. The dot character stands for any single character.
</p>

<pre class="explanation">
if (preg_match($pattern, $word)) {
    echo "$word matches the pattern\n";
} else {
    echo "$word does not match the pattern\n";
}
</pre>

<p>
We test all five words, if they match with the pattern. 
</p>

<pre>
$ php single.php 
Seven matches the pattern
even does not match the pattern
Maven does not match the pattern
Amen does not match the pattern
Leven matches the pattern
</pre>

<p>
The Seven and Leven words match our search pattern. 
</p>

<h2>Anchors</h2>

<p>
Anchors match positions of characters inside a given text. 
</p>

<p>
In the next example, we will look if a string will be located at
the beginning of a sentence. 
</p>

<pre class="code">
&lt;?php

$sentence1 = "Everywhere I look I see Jane";
$sentence2 = "Jane is the best thing that happened to me";

if (preg_match("/^Jane/", $sentence1)) {
    echo "Jane is at the beginning of the \$sentence1\n";
} else {
    echo "Jane is not at the beginning of the \$sentence1\n";
}

if (preg_match("/^Jane/", $sentence2)) {
    echo "Jane is at the beginning of the \$sentence2\n";
} else {
    echo "Jane is not at the beginning of the \$sentence2\n";
}

?&gt;
</pre>

<p>
We have two sentences. The pattern is <b>^Jane</b>. The pattern asks, is the 'Jane' string
located at the beginning of the text?
</p>

<pre>
$ php begin.php 
Jane is not at the beginning of the $sentence1
Jane is at the beginning of the $sentence2
</pre>

<pre class="code">
php > echo preg_match("#Jane$#", "I love Jane");
1
php > echo preg_match("#Jane$#", "Jane does not love me.");
0
</pre>

<p>
The <b>Jane$</b> pattern matches a string, in which the word Jane is at the end.
</p>

<h2>Exact word match</h2>

<p>
In the following examples, we are going to show, how to look for exact word matches.
</p>

<pre class="code">
php &gt; echo preg_match("/mother/", "mother");
1
php &gt; echo preg_match("/mother/", "motherboard");
1
php &gt; echo preg_match("/mother/", "motherland");
1
</pre>

<p>
The <b>mother</b> pattern fits the words mother, motherboard and motherland. Say, we want to 
look just for exact word matches. We will use the aforementioned anchor ^, $ characters.
</p>

<pre class="code">
php &gt; echo preg_match("/^mother$/", "motherland");
0
php &gt; echo preg_match("/^mother$/", "Who is your mother?");
0
php &gt; echo preg_match("/^mother$/", "mother");
1
</pre>

<p>
Using the anchor characters, we get an exact word match for a pattern. 
</p>


<h2>Quantifiers</h2>

<p>
A quantifier after a token or group specifies how often that preceding element is allowed to occur.
</p>

<pre>
 ?     - 0 or 1 match
 *     - 0 or more
 +     - 1 or more
 {n}   - exactly n
 {n,}  - n or more
 {,n}  - n or less (??)
 {n,m} - range n to m
</pre>

<p>
The above is a list of common quantifiers.
</p>

<p>
(?) The question mark indicates there is zero or one of the preceding element.
</p>

<pre class="code">
&lt;?php

$words = array("jar", "jazz", "jay", "java", "jet");

$pattern = "/ja.?/";

foreach ($words as $word) {
    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match pattern\n";
    }
}

?&gt;
</pre>

<p>
We have four words in the <b>$words</b> array. 
</p>

<pre class="explanation">
$pattern = "/colo.?r/";
</pre>

<p>
This is the pattern. The .? combination means, zero or one arbitrary single character.
</p>

<pre>
$ php zeroormore.php 
Seven matches the pattern
even matches the pattern
Maven does not match the pattern
Amen does not match the pattern
Leven matches the pattern
</pre>

<p>
The * metacharacter matches the preceding element zero or more times.
</p>


<pre class="code">
&lt;?php

$words = array("Seven", "even", "Maven", "Amen", "Leven");

$pattern = "/.*even/";

foreach ($words as $word) {
    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match the pattern\n";
    }
}

?&gt;
</pre>

<p>
In the above script, we have added the * metacharacter. The .* combination means, zero, one or more
single characters. 
</p>

<pre>
$ php zeroormore.php 
Seven matches the pattern
even matches the pattern
Maven does not match the pattern
Amen does not match the pattern
Leven matches the pattern
</pre>

<p>
Now the pattern matches three words. Seven, even and Leven. 
</p>

<pre class="code">
php &gt; print_r(preg_grep("#o{2}#", array("gool", "root", "foot", "dog")));
Array
(
    [0] => gool
    [1] => root
    [2] => foot
)
</pre>

<p>
The <b>o{2}</b> pattern matches strings, that have exactly two 'o' characters.
</p>

<pre class="code">
php &gt; print_r(preg_grep("#^\d{2,4}$#", array("1", "12", "123", "1234", "12345")));
Array
(
    [1] => 12
    [2] => 123
    [3] => 1234
)
</pre>

<p>
We have this <b>^\d{2,4}$</b> pattern. The \d is a character set. It stands for digits.
So the pattern matches numbers, that have 2,3 or 4 digits. 
</p>



<h2>Alternation</h2>

<p>
The next example explains the alternation operator (|). This operator
enables to create a regular expression with several choices. 
</p>

<pre class="code">
&lt;?php

$names = array("Jane", "Thomas", "Robert", "Lucy", 
    "Beky", "John", "Peter", "Andy");

$pattern = "/Jane|Beky|Robert/";

foreach ($names as $name) {

    if (preg_match($pattern, $friend)) {
        echo "$name is my friend\n";
    } else {
        echo "$name is not my friend\n";
    }
}

?&gt;
</pre>

<p>
We have 8 names in the <b>$names</b> array. 
</p>


<pre class="explanation">
$pattern = "/Jane|Beky|Robert/";
</pre>

<p>
This is the search pattern. It says, Jane, Beky and Robert are my friends. 
If you find either of them, you have found my friend. 
</p>


<pre>
$ php friends.php 
Jane is my friend
Thomas is not my friend
Robert is my friend
Lucy is not my friend
Beky is my friend
John is not my friend
Peter is not my friend
Andy is not my friend
</pre>

<p>
Output of the script. 
</p>


<h2>Subpatterns</h2>

<p>
We can use square brackets () to create subpatterns inside patterns.
</p>

<pre class="code">
php &gt; echo preg_match("/book(worm)?$/", "bookworm");
1
php &gt; echo preg_match("/book(worm)?$/", "book");
1
php &gt; echo preg_match("/book(worm)?$/", "worm");
0
</pre>

<p>
We have the following regex pattern: <b>book(worm)?$</b>. The <b>(worm)</b> is
a subpattern. The ? character follows the subpattern, which means, that the subpattern
might appear 0,1 times in the final pattern. The $ character is here for the exact end match
of the string. Without it, words like bookstore, bookmania would match too.
</p>

<pre class="code">
php &gt; echo preg_match("/book(shelf|worm)?$/", "book");
1
php &gt; echo preg_match("/book(shelf|worm)?$/", "bookshelf");
1
php &gt; echo preg_match("/book(shelf|worm)?$/", "bookworm");
1
php &gt; echo preg_match("/book(shelf|worm)?$/", "bookstore");
0
</pre>

<p>
Subpatterns are often used with alternation. The <b>(shelf|worm)</b> 
subpattern enables to create several word combinations. 
</p>


<h2>Character classes</h2>

<p>
We can combine characters into character classes with the square brackets.
A character class matches any character, that is specified in the brackets. 
</p>

<pre class="code">
&lt;?php

$words = array("sit", "MIT", "fit", "fat", "lot");

$pattern = "/[fs]it/";

foreach ($words as $word) {

    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match the pattern\n";
    }
}

?&gt;
</pre>

<p>
We define a character set with two characters.  
</p>

<pre class="explanation">
$pattern = "/[fs]it/";
</pre>

<p>
This is our pattern. The [fs] is the character class. Note, that we work 
only with one character at a time. We either consider f, or s. Not both.
</p>

<pre>
$ php chclass.php 
sit matches the pattern
MIT does not match the pattern
fit matches the pattern
fat does not match the pattern
lot does not match the pattern
</pre>

<p>
This is the outcome of the script. 
</p>

<p>
We can also use shorthand metacharacters for character classes. \w stands for alphanumeric characters, 
\d for digit, \s whitespace characters.  
</p>

<pre class="code">
&lt;?php

$words = array("Prague", "111978", "terry2", "mitt##");

$pattern = "/\w{6}/";

foreach ($words as $word) {

    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match the pattern\n";
    }
}

?&gt;
</pre>

<p>
In the above script, we test for words consisting of alphanumeric characters. 
The \w{6} says, six alphanumeric characters match. Only the word mitt## does
not match, because it contains non-alphanumeric characters. 
</p>

<pre class="code">
php &gt; echo preg_match("#[^a-z]{3}#", "ABC");
1
</pre>

<p>
The <b>#[^a-z]{3}#</b> pattern stands for three characters, that are 
not in the class a-z. The "ABC" characters
match the condition.
</p>


<pre class="code">
php &gt; print_r(preg_grep("#\d{2,4}#", array("32", "234", "2345", "3d3", "2")));
Array
(
    [0] => 32
    [1] => 234
    [2] => 2345
)
</pre>

<p>
In the above example, we have a pattern, that matches 2,3,4 digit numbers. 
</p>

<h2>Email example</h2>

<p>
Next have a practical example. We create a regex pattern for checking email
addresses.
</p>


<pre class="code">
&lt;?php

$emails = array("luke@gmail.com", "andy@yahoocom", "34234sdfa#2345", "f344@gmail.com");

# regular expression for emails
$pattern = "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/";

foreach ($emails as $email) {

    if (preg_match($pattern, $email)) {
        echo "$email matches \n";
    } else {
        echo "$email does not match\n";
    }
}

&gt;?
</pre>

<p>
Note that this example provides only one solution. It does not have to be the
best one. 
</p>

<pre class="explanation">
$pattern = "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,5}$/";
</pre>

<p>
This is the pattern. The first ^ and the last $ characters are here to 
get an exact pattern match. No characters before and after the pattern are allowed.
The email is divided into five parts. 
The first part is the local part. This is usually a name of a company, individual or a nickname.
The <b>[a-zA-Z0-9._-]+</b> lists all possible characters, we can use in the local part. 
They can be used one or more times. 
The second part is the literal @ character. The third part is the domain part. It is usually
the domain name of the email provider. Like yahoo, gmail etc. <b>[a-zA-Z0-9-]+</b> It is a character set
providing all characters, than can be used in the domain name. The + quantifier makes use of one or more
of these characters. The fourth part is the dot character. It is preceded by the escape character. (\.)
This is because the dot character is a metacharacter and has a special meaning. By escaping it,
we get a literal dot. Final part is the top level domain. The pattern is as follows: <b>[a-zA-Z.]{2,5}</b>
Top level domains can have from 2 to 5 characters. Like sk, net, info, travel. There is also a dot character.
This is because some top level domains have two parts. For example, co.uk.
</p>

<h2>Recap</h2>

<p>
Finally, we provide a quick recap of the regex patterns. 
</p>

<pre>
Jane    the 'Jane' string
^Jane   'Jane' at the start of a string
Jane$   'Jane' at the end of a string
^Jane$  exact match of the string 'Jane'
[abc]   a, b, or c
[a-z]   any lowercase letter
[^A-Z]  any character that is not a uppercase letter
(Jane|Becky)   Matches either 'Jane' or 'Becky'
[a-z]+   one or more lowercase letters
^[98]?$  digits 9, 8 or empty string       
([wx])([yz])  wy, wz, xy, or xz
[0-9]         any digit
[^A-Za-z0-9]  any symbol (not a number or a letter)
</pre>


<p>
In this chapter, we have covered the regular expressions in PHP. 
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br> 

<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified February 9, 2010  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

